﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.IO;
using System.Collections;

namespace ZeroCross
{
    public class Server
    {
        public static string startUpPath = @".";
        public static Hashtable PlayerList { get; set; }

        private HttpListener listener = null;
        private HttpListenerContext request = null;
        private Thread ListenThread;
        private Thread TimerThread;
        private static Object thisLock = new Object();
        private string prefixes = @"http://+:8811/";
        private int Timeout = 30;
        private bool Flag = false;
        public Server()
        {
            PlayerList = new Hashtable();
        }

        public void Start()
        {
            listener = new HttpListener();
            listener.Prefixes.Add(prefixes);
            listener.Start();

            ListenThread = new Thread(WaitForConnection);
            ListenThread.Start();
            Flag = true;
            TimerThread = new Thread(OnlineTimer);
            TimerThread.Start();
        }

        public void Stop()
        {
            Flag = false;
            listener.Stop();            
        }

        public void WaitForConnection()
        {
            while (true)
            {
                try
                {
                    request = listener.GetContext();
                    string inputCommand = request.Request.Url.LocalPath;
                    string path = Path.Combine(Server.startUpPath, inputCommand);
                    string[] inputData = inputCommand.Split('^');
                    if (inputData.Length > 1)
                    {
                        ClienHandler handler = null;

                        //ищем уже подключенного Обработчика
                        foreach (DictionaryEntry Item in PlayerList)
                        {
                            Player player = (Player)Item.Key;
                            if (inputData[1] == player.Nickname)
                            {
                                handler = (ClienHandler)Item.Value;
                                break;
                            }
                        }

                        //если не нашли делаем новый Обработчик
                        if (handler == null)
                        {                            
                            Player player = new Player();
                            player.OnlineStatus = "online";
                            handler = new ClienHandler(player);
                            player.Nickname = inputData[1];
                            PlayerList.Add(player, handler);
                        }

                        handler.SetRequest(request);
                    }
                    else
                    {
                        Thread FileThread = new Thread(FileRequested);
                        FileThread.Start();
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }

        public void FileRequested()
        {
            lock (thisLock)
            {
                try
                {
                    string inputCommand = Path.GetFileName(request.Request.RawUrl);
                    string path = Path.Combine(Server.startUpPath, inputCommand);
                    byte[] msg = null;

                    if (File.Exists(path))
                    {
                        msg = File.ReadAllBytes(path);
                    }
                    else
                    {
                        msg = File.ReadAllBytes("index.html");
                    }

                    using (Stream s = request.Response.OutputStream)
                    {
                        request.Response.StatusCode = (int)HttpStatusCode.OK;
                        request.Response.ContentLength64 = msg.Length;
                        s.Write(msg, 0, msg.Length);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                finally
                {
                    request.Response.Close();
                    request.Response.Abort();
                }
            }
        }

        private void OnlineTimer()
        {
            while (Flag)
            {
                try
                {
                    if (PlayerList != null)
                    {
                        List<DictionaryEntry> lst= new List<DictionaryEntry>();
                        foreach (DictionaryEntry Item in PlayerList)
                        {
                            Player player = (Player)Item.Key;
                            player.LastOnline++;
                            if (player.LastOnline > Timeout)
                            {
                                player.OnlineStatus = "Disconnected";
                                lst.Add(Item);                               
                            }                                
                        }
                        foreach (DictionaryEntry Item in lst)
                        {
                            PlayerList.Remove(Item.Key);
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                finally
                {
                    Thread.Sleep(1000);
                }
            }
        }

       
    }
}
